<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
<head>

<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title>Troubleshooting : DataMapper ORM - User Guide</title>

<link rel="shortcut icon" type="image/png" href="../images/favicon.png" />
<link rel="stylesheet" type="text/css" media="all" href="../css/userguide.css" />
<link rel="alternate" type="application/rss+xml" title="Datamapper ORM Updates Feed" href="/rss.xml" />

<meta http-equiv="expires" content="-1" />
<meta http-equiv= 'pragma' content="no-cache" />
<meta name="robots" content="all" />

</head>

<body>

<!-- START NAVIGATION -->
<div id="nav"><div id="nav_inner"></div></div>
<div id="nav2"><a name="top">&nbsp;</a><a id="nav_toggle" href="#"><img src="../images/nav_toggle_darker.jpg" width="154" height="43" border="0" title="Toggle Table of Contents" alt="Toggle Table of Contents" /></a></div>
<div id="masthead">
<table cellpadding="0" cellspacing="0" border="0" style="width:100%">
<tr>
<td><h1>DataMapper ORM</h1></td>
<td id="breadcrumb_right"><a href="toc.html">Table of Contents Page</a></td>
</tr>
</table>
</div>
<!-- END NAVIGATION -->

<!-- START BREADCRUMB -->
<table cellpadding="0" cellspacing="0" border="0" style="width:100%">
<tr>
<td id="breadcrumb">
<a href="/">Datamapper ORM Home</a> &nbsp;&#8250;&nbsp;
<a href="../index.html">User Guide Home</a> &nbsp;&#8250;&nbsp;
Troubleshooting
</td>
</tr>

</table>
<!-- END BREADCRUMB -->

<br clear="all" />


<!-- START CONTENT -->
<div id="content">


<h1>Troubleshooting</h1>
<p>If you find you're having problems getting DataMapper to work for you, please check each of the following items for common problems.</p>
<ol>
<li>Be sure to check that your server meets the <a href="requirements.html">Server Requirements</a> and that you have correctly followed the <a href="installation.html">Installation Instructions</a>.</li>

<li>If you have not yet read through all the topics in the <b>General Topics</b> section of the Table of Contents, I recommend you do this now.  There might be some small gem of information you haven't seen which will solve your issue.  I'd also suggest comparing your code against the examples to ensure you are using DataMapper as it was designed.</li>

<li><dfn>Common Issue:</dfn> Check to see that you haven't accidentally overridden any <a href="reservednames.html">Reserved Names</a>.  This is common mistake with relationships, and can lead to unusual behavior.</li>

<li><dfn>Common Issue:</dfn> Double check all of your <a href="#Relationships.NoSave">relationships</a>, taking extra care to make sure that <a href="#Relationships.Symmetric">both sides are configured correctly</a>.</li>

<li>Please read through the FAQs below, to help give you some ideas.  A very useful tip for debugging is &ldquo;<a href="#Database.SeeQuery">How can I see the queries being generated?</a>&rdquo;.</li>

<li>Don't forget to <a href="#" onClick="document.getElementById('googleSearchBox').focus();">search the manual</a>!</li>

</ol>

<div class="note">
	<h3><strong><em>Getting Support</em></strong></h3>
	<p>Primary support for Datamapper ORM is provided through the <a href="http://codeigniter.com/forums/viewthread/149388/">CodeIgniter Forums</a>.  There's a lot of very helpful people there, and I usually respond very quickly!</p>
</div>

<p>In the event you've tried the above but you're still having issues, you are welcome to contact me at the below address.</p>

<div class="important">
	<p><strong><em>Please do not</em></strong> ask for help with messages that says <em>&ldquo;I tried doing X, it didn't work.  Why?&ldquo;</em>, where X looks like an example from the manual.  Between the manual and the forums, you should at least be able to provide some basic troubleshooting.</p>
	<p>Please contact me directly <strong><em>only as a last resort</em></strong> as I prefer to respond on the forums directly, as then everyone can learn.  You can also send me private messages through the forums.</p>
	<p>You can often catch me on IRC, http://irc.freenode.net. Questions I receive via email that do <strong><em>not</em></strong> contain a link to a forum thread discussing the issue will not be dealt with!</p>
	<p id="rot13">Contact Info: <b>JavaScript must be enabled to see my email.</b></p>
</div>

<h1>FAQs</h1>

<p>This is a small list of common issues you may encounter</p>

<ul>
	<li><strong>DataBases</strong>
		<ul>
			<li><a href="#Database.GetFields">Why do I see a bunch of 'SELECT * FROM table LIMIT 1' queries?</a></li>
			<li><a href="#Database.UnknownColumn">Database Error: Unknown Column 'table.*' in 'field list'</a></li>
			<li><a href="#Database.Transactions">Why isn't MySQL using Transactions?</a></li>
			<li><a href="#Database.QueryGrouping">Why is DataMapper returning objects that shouldn't be in my results?</a></li>
			<li><a href="#Database.Ids">Why can I not save an item with a specific ID? Why do I get errors with non-numeric IDs?</a></li>
			<li><a href="#Database.SeeQuery">How can I see the queries being generated?</a></li>
		</ul>
	</li>
	<li><strong>Models</strong>
		<ul>
			<li><a href="#Models.Modules">Does Datamapper support modularity or multiple model folders?</a></li>
		</ul>
	</li>
	<li><strong>General Problems</strong>
		<ul>
			<li><a href="#General.Foreach">Why can't I loop over this result set?</a></li>
			<li><a href="#General.Plural.Unusual">Why is DataMapper generating the wrong table name?</a></li>
			<li><a href="#General.Valid.Object">Why do I get an error saying <i>{Field} must be a valid object or a string</i>?</a></li>
			<li><a href="#General.Plural.Controller">Why do I get a Property or Method Does Not Exist when trying to access a model?</a></li>
			<li><a href="#General.Loading">Why do I see an error that the table 'datamappers' (or similar) does not exist?</a></li>
			<li><a href="#General.Validation">Why isn't DM validating my field?</a></li>
			<li><a href="#General.Extending">What's the best way to add a method I want to use multiple times?</a></li>
			<li><a href="#General.PrintR">Why can't I use <var><b>print_r</b></var>, <var><b>var_dump</b></var>, or <var><b>json_encode</b></var> on a DataMapper model?</a></li>
			<li><a href="#General.Processing">How can I post-process fields after they are loaded?</a></li>
			<li><a href="#General.Processing">How can I pre-process fields before they are saved?</a></li>
			<li><a href="#General.Select.Functions">Why am I getting query errors with select_func?</a></li>
		</ul>
	</li>
	<li><strong>Relationships</strong>
		<ul>
			<li><a href="#Relationships.NoSave">Why is DataMapper not saving a relationship at all?</a></li>
			<li><a href="#Relationships.Symmetric">Why does my relationship work from one object, but fail from the other?</a></li>
			<li><a href="#Relationships.NtoM">Why isn't Datamapper saving the same object more than once?</a></li>
			<li><a href="#Relationships.Delete">Does DataMapper delete related objects automatically?</a></li>
			<li><a href="#Relationships.CascadingDeletes">I have implemented cascading deletes in my RDBMS. Is that a problem?</a></li>
			<li><a href="#Relationships.NotRelated">How do I retrieve all records that do NOT have a relationship?</a></li>
		</ul>
	</li>
</ul>

<h2 id="Database.GetFields">Why do I see a bunch of 'SELECT * FROM table LIMIT 1' queries?</h2>
<p>
	The first time a model is used on a request, DataMapper connects to the database server and loads in the columns for its table.
	These queries often look like this:
</p>
<pre>
<kbd>SELECT</kbd> <dfn>*</dfn> <kbd>FROM</kbd> `users` <kbd>LIMIT</kbd> 1
</pre>

<p>These queries are super-fast. They usually take almost no time to process.</p>
<p>
	However, if you <em>really</em> want to eliminate them, you can do so, using the <a href="prodcache.html">production cache</a>.
	Please read the warning on that page.
</p>

<h2 id="Database.UnknownColumn">Database Error: Unknown Column 'table.*' in 'field list'</h2>
<div class="important">
	<h3><strong><em>CodeIgniter 1.6.x only!</em></strong></h3>
</div>
<p>If you're getting an error that looks very similar to the one below, it's because you need to update your CodeIgniter <strong>MySQL Driver</strong> with the latest version from the <a href="https://bitbucket.org/ellislab/codeigniter/downloads">CodeIgniter downloads</a>.</p>

<pre>A Database Error Occurred

Error Number: 1054

Unknown column `table.*` in 'field list'</pre>

<p>How to update your MySQL Driver:</p>

<ol>
	<li>Get the correct version of the <kbd>mysql_driver.php</kbd> file from the CodeIgniter repository.</li>
	<li>Upload it to your CodeIgniter <kbd>system/database/drivers/mysql</kbd> folder.</li>
</ol>

<p>That's it! The error should now be gone.</p>

<h2 id="Database.Transactions">Why isn't MySQL using Transactions?</h2>
<p>This is almost always caused by using a MySQL database, and not using the correct table type.  Please <a href="http://dev.mysql.com/doc/refman/5.0/en/ansi-diff-transactions.html">see the MySQL website</a> for more information on database table types.</p>

<h2 id="Database.QueryGrouping">Why is DataMapper returning objects that shouldn't be in my results?</h2>
<p>CodeIgniter does not (as of this FAQ) support a way to easily group query clauses with parentheses.  This can lead to unexpected results when combining a <var>AND</var> with an <var>OR</var> clause, because the <var>AND</var> has precedence. For example:</p>
<pre><var>$job</var><kbd>-&gt;</kbd><var><u>where</u></var><kbd>(</kbd><dfn>'new'</dfn><kbd>, </kbd><var><dfn>TRUE</dfn></var><kbd>)-&gt;</kbd><var><u>or_where</u></var><kbd>(</kbd><dfn>'open'</dfn><kbd>, </kbd><var><dfn>TRUE</dfn></var><kbd>)-&gt;</kbd><var><u>where_related</u></var><kbd>(</kbd><var>$user</var><kbd>)-&gt;</kbd><var><u>get</u></var><kbd>();</kbd></pre>
<p>You might expect this to return all <b>new</b> or <b>open</b> jobs by the User <var>$user</var>.  However, the query looks similar to this:
<pre>
<var><kbd>SELECT</kbd> <dfn>*</dfn> <kbd>FROM</kbd> `jobs`
<kbd>WHERE</kbd> `new` <kbd>=</kbd> <dfn>1</dfn> <kbd>OR</kbd> `open` <kbd>=</kbd> <dfn>1</dfn> <kbd>AND</kbd> `user_id` <kbd>=</kbd> <dfn>5</dfn></var>
</pre>
This means that the query will select all jobs that are <b>new</b> OR are both <b>open</b> AND assigned to <var>$user</var>.</p>
<p>However, Datamapper ORM <em>does</em> support query grouping.  This means you can structure your query like this:</p>
<pre>
<var>$job</var><kbd>-&gt;</kbd><em class="new"><var><u>group_start</u></var><kbd>()-&gt;</kbd></em><var><u>where</u></var><kbd>(</kbd><dfn>'new'</dfn><kbd>, </kbd><var><dfn>TRUE</dfn></var><kbd>)-&gt;</kbd><var><u>or_where</u></var><kbd>(</kbd><dfn>'open'</dfn><kbd>, </kbd><var><dfn>TRUE</dfn></var><kbd>)-&gt;</kbd><em class="new"><var><u>group_end</u></var><kbd>()-&gt;</kbd></em><var><u>where_related</u></var><kbd>(</kbd><var>$user</var><kbd>)-&gt;</kbd><var><u>get</u></var><kbd>();</kbd>
</pre>
<p>And your query will now look similar to this:</p>
<pre>
<var><kbd>SELECT</kbd> <dfn>*</dfn> <kbd>FROM</kbd> `jobs`
<kbd>WHERE</kbd> <kbd>(</kbd>`new` <kbd>=</kbd> <dfn>1</dfn> <kbd>OR</kbd> `open` <kbd>=</kbd> <dfn>1</dfn><kbd>)</kbd> <kbd>AND</kbd> `user_id` <kbd>=</kbd> <dfn>5</dfn></var>
</pre>

<h2 id="Database.Ids">Why do I get errors with non-numeric IDs?</h2>
<p>DataMapper only works with automatically generated, numerical IDs.</p>
<p>There is no way around either limitation.  If you need to store a unique value that is not serially generated, I recommend storing it in a different field on the table.  You still need an ID column, but the other column can still be UNIQUE and indexed.</p>
<p>Note that you can now <a href="save.html#Save.Existing.As.New">force an object with an ID to be inserted</a>.</p>

<h2 id="Database.SeeQuery">How can I see the queries being generated?</h2>
<p>The CodeIgniter Profiler provides a lot of information about what was happening.  This is useful for when there was no output.</p>

<h3>Enabling the Profiler</h3>
<pre>
<samp>// In Controller
</samp><var><b>$this</b></var><kbd>-&gt;</kbd><var>output</var><kbd>-&gt;</kbd><var>enable_profiler</var><kbd>(</kbd><var><dfn>TRUE</dfn></var><kbd>);</kbd>
</pre>

<p>In the event that the profiler has TOO much information, or you are outputting to a non-HTML format (such as JSON information), use <var>$object</var><kbd>-&gt;</kbd><var><u>check_last_query</u></var><kbd>()</kbd>. (<a href="utility.html#check_last_query">More detailed information.</a>)</p>

<h3>Getting the Last Generated Query</h3>
<pre>
<var>$object</var><kbd>-&gt;</kbd><var><u>where</u></var><kbd>(</kbd><dfn>'thing'</dfn><kbd>, </kbd><var><dfn>TRUE</dfn></var><kbd>)-&gt;</kbd><var><u>get</u></var><kbd>();
</kbd><var>$last_query </var><kbd>= </kbd><var>$object</var><kbd>-&gt;</kbd><var><u>check_last_query</u></var><kbd>(</kbd><dfn>FALSE</dfn><kbd>,</kbd> <dfn>TRUE</dfn><kbd>);</kbd>
</pre>
<p><strong>$last_query</strong> would contain something like:</p>
<pre>
SELECT `objects`.*
FROM `objects`
WHERE `objects`.`thing` = 1
</pre>

<h2 id="Models.Modules">Does Datamapper support modularity or multiple model folders?</h2>
<h3>1.8.1 and newer:</h3>
<p>Datamapper supports model classes from CodeIgniter 2.0+ packages, HMVC Modular Extensions and Modular CI modules, or through the <a href="advancedusage.html#add_model_path">add_model_path</a> static method.</p>

<h2 id="General.Foreach">Why can't I loop over this result set?</h2>
<h3>1.7.0 and newer:</h3>
<p>The recommended method from this version on is to <b>not</b> specify the <var><i>all</i></var> array any more.  If you are using <var><u>get_iterated</u></var>, you cannot specify the array, as it is not populated.</p>
<pre>
<samp>// recommended format.
</samp><kbd>foreach(</kbd><var>$object </var><kbd>as </kbd><var>$o</var><kbd>) {
    echo </kbd><var>$o</var><kbd>-&gt;</kbd><var>value</var><kbd>;
}</kbd>
</pre>
<div class="highlight">
	<h3>1.4.1 and earlier:</h3>
	<p>You must loop over <var>$object</var><kbd>-&gt;</kbd><var><i>all</i></var>, <strong>not</strong> <var>$object</var> directly.</p>
<pre>
<kbd>foreach(</kbd><var>$object</var><em class="new"><kbd>-&gt;</kbd><var><i>all</i></var></em> <kbd>as </kbd><var>$o</var><kbd>) {
    echo </kbd><var>$o</var><kbd>-&gt;</kbd><var>value</var><kbd>;
}</kbd>
</pre>
	<p>(From 1.4.2 on, you can loop over <var>$object</var> directly, and it will loop over the <var><i>all</i></var> array automatically.</p>
</div>

<h2 id="General.Plural.Unusual">Why is DataMapper generating the wrong table name?</h2>
<p>While datamapper is very good at commonly pluralized english words, sometimes it stumbles on common words such as <strong>Address</strong>.  In these cases, you must manually specify the table name, by adding <var><i>$table</i></var> (plural) and sometimes <var><i>$model</i></var> (singular) to the model definition.</p>
<p>For an example, see the Country model on the <a href="models.html#rules">DataMapper Models</a> page.</p>
<p class="note">Many of these problems have been fixed with the updated <b>inflector_helper</b>, which comes with Datamapper ORM.  If you have installed it, but still have issues, please contact me with the specific words (on the forum or above) and I'll try to update the inflector helper.</p>

<h2 id="General.Valid.Object">Why do I get an error saying <i>{Field} must be a valid object or a string</i>?</h2>
<p>This error will occur whenever you have incorrectly configured your relationships. <a href="#Relationships.Symmetric">See this FAQ for more information.</a></p>

<h2 id="General.Plural.Controller">Why do I get a Property or Method Does Not Exist when trying to access a model?</h2>
<p>The most common reason for this is having the same name for both a <strong>Controller</strong> and a <strong>Model</strong>.  Because DataMapper models are PHP Objects, they share the PHP namespace with the controllers.  This means you cannot have a model named <dfn>User</dfn> and a controller also named <kbd>User</kbd>.  Instead, it is recommended that you use <em>plural</em> names on the controllers.</p>
<p>What's that?  You have a model named <strong>moose</strong> or <strong>fruit</strong>, or just really like the singular form?  Well, you can solve this in several ways:</p>
<ul>
	<li>Rename your model, such as <var>MyMoose</var> (but then you have to rename your tables, etc.).</li>
	<li>Use <a href="http://codeigniter.com/user_guide/general/routing.html">CodeIgniter Routing</a> to re-route the url to your pluralized controller. (<strong>Recommended where possible</strong>)</li>
	<li>Use an <dfn>.htaccess</dfn> file to rewrite the url to the pluralized controller.  That's beyond the scope of this document.</li>
</ul>

<h2 id="General.Loading">Why do I see an error that the table 'datamappers' (or similar) does not exist?</h2>
<p>You probably instantiated the DataMapper library.  You also might have an object whose table name is not generated correctly.  See <a href="#General.Plural.Unusual">Why is DataMapper generating the wrong table name?</a> above.</p>

<h2 id="General.Validation">Why isn't DM validating my field?</h2>
<p>There are two main reasons for this.  Both will easily confuse you at first:</p>
<ol>
	<li>The most common reason for this a field without a <dfn>'required'</dfn> rule.  You <em>must</em> include this rule for any field that needs to be non-empty.  This is done to prevent PHP errors when validating empty fields.  If a field is empty, but not required, then the validation routine skips that field.</li>
	<li>Alternatively, the field probably did not change.  If the field is not changed between loading an object and saving it, then the field will not be validated.  This prevents running the same validation more than once (such as for encrypted fields).</li>
</ol>

<h2 id="General.Extending">What's the best way to add a method I want to use multiple times?</h2>
<p>See <a href="extensions.html">Extending DataMapper</a>.</p>

<h2 id="General.PrintR">Why can't I use <var><b>print_r</b></var>, <var><b>var_dump</b></var>, or <var><b>json_encode</b></var> on a DataMapper model?</h2>
<p>DataMapper models have two specific reasons why these methods will fail to work.</p>
<ol>
	<li>Most of the fields are generated dynamically, including all relationships. This mean that these items will not exist until the first time they are called.</li>
	<li>Because the relationships can end up recursive (the first item in the <var><i>all</i></var> array is also the containing object), you can sometimes cause <dfn>print_r</dfn> to get into an infinite loop.</li>
</ol>
<p>Instead of these methods, you might want to look at specific fields, one-at-a-time.  Also, in the future, I might include a debugging extension.</p>
<p>To replace the <var><b>json_encode</b></var> method, please take a look at the <a href="extensions/json.html">json</a> and <a href="extensions/array.html">array</a> extensions.</p>

<h2 id="General.Processing">How can I post-process fields after they are loaded?<br/>
		How can I pre-process fields before they are saved?</h2>
<p>You can post-process fields after a get using <a href="getrules.html">Get Rules</a>.</p>
<p>You can pre-process fields before a save using <a href="validation.html">Validation Rules</a>.  See <a href="examples/login.html">Handling Logins</a> for an example of pre-processing.</p>

<h2 id="General.Select.Functions">Why am I getting query errors with select_func?</h2>
<p>
	CodeIgniter has an overly aggressive method for protecting identifiers, and it <strong>cannot</strong> be disabled.
	This may break any attempt to include functions in the SELECT statement.
</p>
<p>However, with a simple adjustment to the <var>_protect_identifiers</var> method of the <var>DB_driver</var> class, you can get it working again.</p>
<p><a href="functions.html#Protect.Identifiers.Fix">See the bottom of this page for a fix.</a></p>

<h2 id="Relationships.NoSave">Why is DataMapper not saving a relationship at all?</h2>
<p>The most common cause for this is a mistake in one or both sides of your relationship definition.  Make sure that the <var><i>$has_many</i></var> or <var><i>$has_one</i></var> definition on both objects is correct.</p>

<p>A less common cause for this would be that you enabled the <a href="prodcache.html">Production Cache</a>, but forgot to disable or clear it after making changes.</p>

<h2 id="Relationships.Symmetric">Why does my relationship work from one object, but fail from the other?</h2>
<p>When configuring a relationship, even a self-relationship, you must define both "sides" of the relationship.  This means for a <var><s>parent</s></var>/<var><i>child</i></var> relationship, you have to specify the <var><s>parent</s></var> on the <var><i>child</i></var>, <strong>and</strong> you have to specify the <var><i>child</i></var> on the <var><s>parent</s></var>.</p>
<p>Here is an example for a complex self-relationship [User (as Boss) has many Employees, and Employees have one Boss]:
<pre>
<samp>// In User
</samp><var>$has_one </var><kbd>= array(
    </kbd><samp>// define the relationship to the boss
    </samp><var><s>'boss'</s></var> <kbd>=&gt; array(
        </kbd><dfn>'class' </dfn><kbd>=&gt; </kbd><dfn>'user'</dfn><kbd>,
        </kbd><dfn>'other_field' </dfn><kbd>=&gt; </kbd><var><i>'employee'</i></var>
    <kbd>)
);

</kbd><var>$has_many </var><kbd>= array(
    </kbd><samp>// define the relationship to the employees
    </samp><var><i>'employee'</i></var> <kbd>=&gt; array(
        </kbd><dfn>'class' </dfn><kbd>=&gt; </kbd><dfn>'user'</dfn><kbd>,
        </kbd><dfn>'other_field' </dfn><kbd>=&gt; </kbd><var><s>'boss'</s></var>
    <kbd>)
);</kbd>
</pre>
Now the <var><i>employee</i></var>s can be access as <var><s>$a_boss</s></var><kbd>-&gt;</kbd><var><i>employee</i></var><kbd>-&gt;</kbd><var><u>get</u></var><kbd>()</kbd>, and <var><s>boss</s></var>es could be accessed as <var><i>$an_employee</i></var><kbd>-&gt;</kbd><var><s>boss</s></var><kbd>-&gt;</kbd><var><u>get</u></var><kbd>()</kbd>.</p>

<h2 id="Relationships.NtoM">Why isn't Datamapper saving the same object more than once?</h2>
<p>Due to the way DataMapper looks at objects, it is incapable of storing a relationship between the same objects more than once, <strong>even when using extra join table columns</strong>.</p>
<p>The best solution for this is to use a couple of other features that are unique to Datamapper ORM to store the relationship in a dedicated model. A very rudimentary example is provided below, joining Machine and Part, feel free to enhance it:</p>
<pre>
<samp>// ------------------------------
// create this model:
// ------------------------------
</samp><kbd>class </kbd><var>MachinePart </var><kbd>extends </kbd><var><u>DataMapper</u> </var><kbd>{
    </kbd><var><i>$has_one</i> </var><kbd>= array(</kbd><dfn>'machine'</dfn><kbd>, </kbd><dfn>'part'</dfn><kbd>);
    </kbd><samp>// etc.
</samp><kbd>}

</kbd><samp>// ------------------------------
// create this table:
// ------------------------------
</samp><var>machineparts</var><kbd>: </kbd><var>id</var><kbd>, </kbd><var>machine_id</var><kbd>, </kbd><var>part_id</var><kbd>, </kbd><var>setting_1</var><kbd>, </kbd><var>setting_2</var><kbd>, ...

</kbd><samp>// ------------------------------
// Use it like this in a controller:
// ------------------------------
// add a part to a machine
</samp><var>$m </var><kbd>= new </kbd><var>Machine</var><kbd>(); ...
</kbd><var>$p </var><kbd>= new </kbd><var>Part</var><kbd>(); ...
</kbd><var>$mp </var><kbd>= new </kbd><var>MachinePart</var><kbd>();
</kbd><var>$mp</var><kbd>-&gt;</kbd><var>setting_1 </var><kbd>= </kbd><var>$setting_1_value</var><kbd>;
</kbd><var>$mp</var><kbd>-&gt;</kbd><var><u>save</u></var><kbd>(array(</kbd><var>$m</var><kbd>, </kbd><var>$p</var><kbd>));

</kbd><samp>// get all parts for the machine $m
</samp><var>$parts </var><kbd>= </kbd><var>$m</var><kbd>-&gt;</kbd><var>machinepart</var><kbd>;
</kbd><samp>// simple trick to avoid making multiple queries
</samp><var>$parts</var><kbd>-&gt;</kbd><var><u>join_related</u></var><kbd>(</kbd><dfn>'part'</dfn><kbd>, </kbd><dfn>'*'</dfn><kbd>, </kbd><var><dfn>FALSE</dfn></var><kbd>); </kbd><samp>// join all ('*') parts fields, with no prefix
</samp><var>$parts</var><kbd>-&gt;</kbd><var><u>get</u></var><kbd>();
foreach(</kbd><var>$parts</var><kbd> as </kbd><var>$part</var><kbd>) {
    echo(</kbd><var>$part</var><kbd>-&gt;</kbd><var>name</var><kbd>); </kbd><samp>// from the Parts table
    </samp><kbd>echo(</kbd><var>$part</var><kbd>-&gt;</kbd><var>setting_1</var><kbd>); </kbd><samp>// from the MachineParts table
    </samp><kbd>echo(</kbd><var>$part</var><kbd>-&gt;</kbd><var>setting_2</var><kbd>);
    ...
}

</kbd><samp>// remove all machine-part relationships
</samp><var>$m</var><kbd>-&gt;</kbd><var>machinepart</var><kbd>-&gt;</kbd><var><u>get</u></var><kbd>()-&gt;</kbd><var><u>delete_all</u></var><kbd>();

</kbd><samp>// remove a specific machine-part relationship, by id
</samp><var>$mp </var><kbd>= new </kbd><var>MachinePart</var><kbd>();
</kbd><var>$mp</var><kbd>-&gt;</kbd><var><u>get_by_id</u></var><kbd>(</kbd><var>$mp_id</var><kbd>);
</kbd><var>$mp</var><kbd>-&gt;</kbd><var><u>delete</u></var><kbd>(); </kbd><samp>// also removes relationships</samp>
</pre>

<p>Using this as a base, you can see how to relate, query, and delete a N:M relationship where the objects need to be related multiple times.

<h2 id="Relationships.Delete">Does DataMapper delete related objects automatically?</h2>
<p>In short, no.  DataMapper automatically deletes the relationship between two objects if you delete one of those objects.  However, it does not delete related objects automatically.</p>
<p>If you need to handle this in multiple locations, I recommend creating an extra method on the model (I usually call <var>delete_deep()</var>), and delete the related objects you want removed.</p>

<h2 id="Relationships.CascadingDeletes">I have implemented cascading deletes in my RDBMS. Is that a problem?</h2>
<p>No, as long as you have installed Datamapper v1.8.1 or higher, and have configured Datamapper to not automatically remove relations when deleting an object.</p>
<p>To disable automatic deletion of relations, set the config variable <var>cascade_delete</var> to <var><dfn>FALSE</dfn></var>. You can do this globally, per model and per relation.</p>
<p>You need to disable this option (set to <var><dfn>FALSE</dfn></var>) when you use 'ON DELETE CASCADE' in your RDBMS.</p>

<h2 id="Relationships.NotRelated">How do I retrieve all records that do NOT have a relationship?</h2>
<p>Exactly like you would do it when you write your native SQL statement: using a subquery:</p>
<pre>
<samp>// find all books related to user "John"</samp>
<var>$sub_books</var> <kbd>= new</kbd> <var>Book</var><kbd>();</kbd>
<var>$sub_books</var><kbd>-></kbd><var><u>select</u></var><kbd>(</kbd><dfn>'id'</dfn><kbd>)-></kbd><var><u>where_related_user</u></var><kbd>(</kbd><dfn>'name'</dfn><kbd>,</kbd> <dfn>"John"<dfn><kbd>);</kbd>

<samp>// now get all books not related</samp>
<var>$book</var><kbd> = new </kbd><var>Book</var><kbd>();</kbd>
<var>$book</var><kbd>-></kbd><var><u>where_not_in_subquery</u></var><kbd>(</kbd><dfn>'id'</dfn><kbd>,</kbd> <var>$sub_books</var><kbd>)-></kbd><var><u>get</u></var><kbd>();</kbd>
</pre>
<p>This will generate the following query, exactly like you would code it by hand:</p>
<pre>
<var>SELECT *
FROM (<dfn>`books`</dfn>)
WHERE books.id NOT IN (SELECT <dfn>`books_subquery`</dfn>.<dfn>`id`</dfn>
 FROM <dfn>`books`</dfn> <dfn>`books_subquery`</dfn>
 LEFT OUTER JOIN <dfn>`books_users`</dfn> books_users ON <dfn>`books_subquery`</dfn>.<dfn>`id`</dfn> = <dfn>`books_users`</dfn>.<dfn>`book_id`</dfn>
 WHERE <dfn>`books_users`</dfn>.<dfn>`book_id`</dfn> IN (<dfn>1</dfn>, <dfn>16</dfn>, <dfn>23</dfn>) )
</var></pre>
<p>A more complex example:</p>
<pre>
<samp>// create the parent and child objects</samp>
<var>$parent</var> <kbd>= new</kbd> <var>Parent</var><kbd>();</kbd>
<var>$child</var> <kbd>=</kbd> <var>$parent</var><kbd>-></kbd><var>child</var><kbd>;</kbd>

<samp>// subquery: select all parent_id's of parent related to child with id 1</samp>
<var>$child</var><kbd>-></kbd><var><u>select</u></var><kbd>(</kbd><dfn>'parent_id'</dfn>);
<var>$child</var><kbd>-></kbd><var><u>where</u></var><kbd>(</kbd><dfn>'child_id'</dfn>, <dfn>1</dfn><kbd>);</kbd>
<var>$child</var><kbd>-></kbd><var><u>where_related</u></var><kbd>(</kbd><dfn>'parent'</dfn><kbd>,</kbd> <dfn>'id'</dfn><kbd>,</kbd> <dfn>'${parent}.id'</dfn><kbd>);</kbd>

<samp>// now retrieve all parents that are NOT related to child with id 1</samp>
<var>$parent</var><kbd>-></kbd><var><u>where_not_in_subquery</u></var><kbd>(</kbd><dfn>'id'</dfn><kbd>,</kbd> <var>$child</var><kbd>)-></kbd><var><u>get</u></var><kbd>();</kbd>
</pre>
</div>
<!-- END CONTENT -->


<div id="footer">
<p>
<span id="footer_previous">Previous Topic:&nbsp;&nbsp;<a href=""></a>
&nbsp;&nbsp;&nbsp;&middot;&nbsp;&nbsp;</span>
<a href="#top">Top of Page</a>&nbsp;&nbsp;&nbsp;&middot;&nbsp;&nbsp;
<a href="../index.html">User Guide Home</a>
<span id="footer_next">&nbsp;&nbsp;&nbsp;&middot;&nbsp;&nbsp;
Next Topic:&nbsp;&nbsp;<a href=""></a></span>
</p>
<div id="copyrights">
<p><a href="/">Datamapper ORM</a> &nbsp;&middot;&nbsp; Copyright &copy; 2010-2011 &nbsp;&middot;&nbsp; Harro "WanWizard" Verton</p>
<p><a href="license.html">Other License Information</a></p>
</div>
</div>

<script type="text/javascript" src="../js/mootools.js"></script>
<script type="text/javascript" src="../js/menu.js"></script>
<script type="text/javascript" src="../js/rot13.js"></script>
<script type="text/javascript">
<!--
	window.addEvent('domready', function() {

		// Create Menu
		var menu = new Menu({
			basepath: '../',
			pagespath: ''
		});

		// Create ROT13
		var rot = new ROT13();

		$('rot13').set('html', 'Contact Info: ' + rot.convert('<n uers="znvygb:qngnznccre@jnajvmneq.rh">Uneeb Iregba</n>'));
	});
//-->
</script>
</body>
</html>
